<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram Reproduction</title>
</head>
<body>
<canvas id="physicsCanvas" width="850" height="450"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Style settings to mimic hand-drawn look ---
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2.5;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';

    // --- Custom Character Drawing Functions ---
    // A helper to call the specific drawing function for a character
    function drawChar(char, x, y, s) {
        switch (char) {
            case 'Q': draw_Q(x, y, s); break;
            case '1': draw_1(x, y, s); break;
            case '2': draw_2(x, y, s); break;
            case '+': draw_plus(x, y, s); break;
            case '-': draw_minus(x, y, s); break;
            case 'r': draw_r(x, y, s); break;
            case 'R': draw_R(x, y, s); break;
            case 'θ': draw_theta(x, y, s); break;
            case 'α': draw_alpha(x, y, s); break;
            case 'F': draw_F(x, y, s); break;
            case 'i': draw_i(x, y, s); break;
            case 'g': draw_g(x, y, s); break;
            case '.': draw_dot(x, y, s); break;
            case '5': draw_5(x, y, s); break;
            case '7': draw_7(x, y, s); break;
            case '8': draw_8(x, y, s); break;
        }
    }

    function draw_Q(x, y, s) {
        ctx.beginPath();
        ctx.ellipse(x, y, s * 0.35, s * 0.4, 0, 0, Math.PI * 2);
        ctx.moveTo(x + s * 0.15, y + s * 0.2);
        ctx.lineTo(x + s * 0.45, y + s * 0.5);
        ctx.stroke();
    }
    function draw_1(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x, y - s * 0.3);
        ctx.lineTo(x - s * 0.2, y - s * 0.1);
        ctx.moveTo(x, y - s * 0.3);
        ctx.lineTo(x, y + s * 0.3);
        ctx.stroke();
    }
    function draw_2(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x - s * 0.3, y - s * 0.1);
        ctx.arc(x, y - s * 0.1, s * 0.3, Math.PI, 0);
        ctx.lineTo(x - s * 0.3, y + s * 0.3);
        ctx.moveTo(x - s * 0.35, y + s * 0.3);
        ctx.lineTo(x + s * 0.35, y + s * 0.3);
        ctx.stroke();
    }
    function draw_plus(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x - s * 0.3, y);
        ctx.lineTo(x + s * 0.3, y);
        ctx.moveTo(x, y - s * 0.3);
        ctx.lineTo(x, y + s * 0.3);
        ctx.stroke();
    }
    function draw_minus(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x - s * 0.3, y);
        ctx.lineTo(x + s * 0.3, y);
        ctx.stroke();
    }
    function draw_r(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x - s * 0.1, y + s * 0.3);
        ctx.lineTo(x - s * 0.1, y - s * 0.1);
        ctx.arc(x, y - s * 0.1, s * 0.2, Math.PI * 0.8, 0);
        ctx.stroke();
    }
    function draw_R(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x - s * 0.2, y + s * 0.4);
        ctx.lineTo(x - s * 0.2, y - s * 0.4);
        ctx.lineTo(x + s * 0.2, y - s * 0.4);
        ctx.arc(x + 0.05 * s, y - 0.1 * s, 0.3 * s, -Math.PI / 2, Math.PI / 2);
        ctx.lineTo(x + s * 0.3, y + s * 0.4);
        ctx.stroke();
    }
    function draw_theta(x, y, s) {
        ctx.beginPath();
        ctx.ellipse(x, y, s * 0.35, s * 0.35, 0, 0, Math.PI * 2);
        ctx.moveTo(x - s * 0.35, y);
        ctx.lineTo(x + s * 0.35, y);
        ctx.stroke();
    }
    function draw_alpha(x, y, s) {
        ctx.beginPath();
        ctx.moveTo(x + s * 0.3, y + s * 0.2);
        ctx.arc(x, y, s * 0.3, 0.2, Math.PI - 0.2, true);
        ctx.arc(x, y, s * 0.3, Math.PI + 0.2, Math.PI * 2 - 0.2, true);
        ctx.closePath();
        ctx.stroke();
    }
    function draw_F(x, y, s) { ctx.beginPath(); ctx.moveTo(x + s*0.2, y - s*0.4); ctx.lineTo(x - s*0.2, y - s*0.4); ctx.lineTo(x - s*0.2, y + s*0.4); ctx.moveTo(x - s*0.2, y); ctx.lineTo(x + s*0.1, y); ctx.stroke(); }
    function draw_i(x, y, s) { ctx.beginPath(); ctx.moveTo(x, y - s*0.1); ctx.lineTo(x, y + s*0.3); ctx.stroke(); ctx.beginPath(); ctx.arc(x, y - s*0.3, s*0.06, 0, Math.PI*2); ctx.fill();}
    function draw_g(x, y, s) { ctx.beginPath(); ctx.ellipse(x, y, s*0.25, s*0.25, 0, 0, Math.PI*2); ctx.moveTo(x+s*0.25, y-s*0.1); ctx.lineTo(x+s*0.25, y+s*0.4); ctx.arc(x, y+s*0.4, s*0.25, 0, Math.PI); ctx.stroke();}
    function draw_dot(x, y, s) { ctx.beginPath(); ctx.arc(x, y, s * 0.1, 0, Math.PI * 2); ctx.fill();}
    function draw_5(x, y, s) { ctx.beginPath(); ctx.moveTo(x + s*0.3, y - s*0.3); ctx.lineTo(x - s*0.3, y - s*0.3); ctx.lineTo(x - s*0.3, y); ctx.arc(x, y + s*0.05, s*0.3, Math.PI, Math.PI*1.8); ctx.stroke(); }
    function draw_7(x, y, s) { ctx.beginPath(); ctx.moveTo(x-s*0.3, y-s*0.3); ctx.lineTo(x+s*0.3, y-s*0.3); ctx.lineTo(x-s*0.1, y+s*0.4); ctx.stroke(); }
    function draw_8(x, y, s) { ctx.beginPath(); ctx.ellipse(x, y-s*0.15, s*0.25, s*0.18, 0, 0, Math.PI*2); ctx.ellipse(x, y+s*0.2, s*0.28, s*0.22, 0, 0, Math.PI*2); ctx.stroke(); }

    // Text rendering function that handles strings and subscripts
    function drawText(str, x, y, size = 20) {
        let currentX = x;
        for (let i = 0; i < str.length; i++) {
            const char = str[i];
            const nextChar = str[i + 1];
            
            if (nextChar === '_' || nextChar === '+') {
                const mainChar = char;
                const subChar = str[i + 2];
                const subSize = size * 0.7;
                drawChar(mainChar, currentX, y, size);
                drawChar(subChar, currentX + size * 0.4, y + size * 0.3, subSize);
                if (nextChar === '+') { // for r+
                   drawChar('+', currentX + size * 0.4 - subSize*0.1, y + size * 0.3 - subSize*0.3, subSize*0.8);
                } else if (nextChar === '_') { // for r-
                   drawChar('-', currentX + size * 0.4, y + size * 0.3 + subSize*0.3, subSize*0.8);
                }
                currentX += size * 0.8;
                i += 2;
            } else if (char === ' ') {
                currentX += size * 0.5;
            } else {
                drawChar(char, currentX, y, size);
                currentX += size * 0.6;
            }
        }
    }


    // --- Generic Drawing Primitives ---
    function drawLine(x1, y1, x2, y2, dashed = false) {
        ctx.beginPath();
        if (dashed) {
            ctx.setLineDash([5, 5]);
        }
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
        if (dashed) {
            ctx.setLineDash([]);
        }
    }

    function drawArrow(x1, y1, x2, y2) {
        drawLine(x1, y1, x2, y2);
        const angle = Math.atan2(y2 - y1, x2 - x1);
        const size = 12;
        ctx.beginPath();
        ctx.moveTo(x2, y2);
        ctx.lineTo(x2 - size * Math.cos(angle - Math.PI / 6), y2 - size * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(x2, y2);
        ctx.lineTo(x2 - size * Math.cos(angle + Math.PI / 6), y2 - size * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }

    function drawPoint(x, y, radius = 4) {
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2);
        ctx.fill();
    }
    
    function drawAngleArc(cx, cy, r, startAngle, endAngle, ccw = false) {
        ctx.beginPath();
        ctx.arc(cx, cy, r, startAngle, endAngle, ccw);
        ctx.stroke();
    }


    // --- Draw Figure 1.57 ---
    function drawFig1_57() {
        const origin = { x: 130, y: 350 };
        const r = 160;
        const R = 35;
        const theta_deg = 30;
        const alpha_deg = 40;

        const theta_rad = theta_deg * Math.PI / 180;
        const alpha_rad = alpha_deg * Math.PI / 180;

        const center = {
            x: origin.x + r * Math.cos(theta_rad),
            y: origin.y - r * Math.sin(theta_rad)
        };

        const r_angle_canvas = -theta_rad;
        const perp_angle_canvas = r_angle_canvas - Math.PI / 2;
        const dipole_angle_canvas = perp_angle_canvas + alpha_rad;

        const p_plus_q2 = {
            x: center.x + R * Math.cos(dipole_angle_canvas),
            y: center.y + R * Math.sin(dipole_angle_canvas)
        };
        const p_minus_q2 = {
            x: center.x - R * Math.cos(dipole_angle_canvas),
            y: center.y - R * Math.sin(dipole_angle_canvas)
        };

        // Axis
        drawArrow(origin.x, origin.y, origin.x + 240, origin.y);
        
        // Q1 and r
        drawText("Q_1", origin.x - 40, origin.y + 10, 24);
        drawLine(origin.x, origin.y, center.x, center.y);
        drawText("r", (origin.x + center.x) / 2 - 20, (origin.y + center.y) / 2 - 10, 24);
        
        // Theta angle
        drawAngleArc(origin.x, origin.y, 50, 0, r_angle_canvas, true);
        drawText("θ", origin.x + 60, origin.y - 20, 24);

        // Dipole
        drawLine(p_plus_q2.x, p_plus_q2.y, p_minus_q2.x, p_minus_q2.y);
        drawPoint(p_plus_q2.x, p_plus_q2.y, 4);
        drawPoint(p_minus_q2.x, p_minus_q2.y, 4);
        drawText("+Q_2", p_plus_q2.x - 20, p_plus_q2.y - 30, 24);
        drawText("-Q_2", p_minus_q2.x, p_minus_q2.y + 15, 24);
        
        // Alpha angle and R indicator
        const perp_end = {
            x: center.x + (R + 10) * Math.cos(perp_angle_canvas),
            y: center.y + (R + 10) * Math.sin(perp_angle_canvas)
        };
        drawLine(center.x, center.y, perp_end.x, perp_end.y, true);
        drawAngleArc(center.x, center.y, 25, perp_angle_canvas, dipole_angle_canvas);
        const alpha_label_angle = (perp_angle_canvas + dipole_angle_canvas) / 2;
        drawText("α", center.x + 35 * Math.cos(alpha_label_angle), center.y + 35 * Math.sin(alpha_label_angle), 24);

        // Dashed box for R
        const corner1 = {x: p_minus_q2.x, y: p_minus_q2.y};
        // Project vector (center -> p_minus_q2) onto the perpendicular line
        const dot_p = (corner1.x - center.x) * Math.cos(perp_angle_canvas) + (corner1.y - center.y) * Math.sin(perp_angle_canvas);
        const corner2 = {
            x: center.x + dot_p * Math.cos(perp_angle_canvas),
            y: center.y + dot_p * Math.sin(perp_angle_canvas)
        };
        drawLine(corner1.x, corner1.y, corner2.x, corner2.y, true);
        drawLine(center.x, center.y, corner2.x, corner2.y, true);
        
        const R_label_pos = {
            x: (center.x + corner2.x) / 2 + 10 * Math.cos(r_angle_canvas),
            y: (center.y + corner2.y) / 2 + 10 * Math.sin(r_angle_canvas)
        }
        drawText("R", R_label_pos.x, R_label_pos.y, 24);

        // Figure label
        drawText("Fig. 1.57", 180, 420, 24);
    }

    // --- Draw Figure 1.58 ---
    function drawFig1_58() {
        const origin = { x: 500, y: 350 };
        const O = origin;
        const A = { x: 700, y: 150 }; // Corresponds to +Q2
        const B = { x: 720, y: 230 }; // Corresponds to -Q2
        const M = { x: (A.x + B.x) / 2, y: (A.y + B.y) / 2 };

        // Axis
        drawArrow(origin.x, origin.y, origin.x + 320, origin.y);

        // Triangle
        drawLine(O.x, O.y, A.x, A.y); // r+
        drawLine(O.x, O.y, B.x, B.y); // r-
        drawLine(A.x, A.y, B.x, B.y); // 2R
        drawLine(O.x, O.y, M.x, M.y); // r

        // Labels
        drawText("r", (O.x + A.x) / 2 - 30, (O.y + A.y) / 2, 24);
        drawText("+", (O.x + A.x) / 2 - 12, (O.y + A.y) / 2 + 12, 12);

        drawText("r", (O.x + B.x) / 2, (O.y + B.y) / 2 + 10, 24);
        drawText("_", (O.x + B.x) / 2 + 10, (O.y + B.y) / 2 + 12, 12);
        
        drawText("r", (O.x + M.x) / 2 + 5, (O.y + M.y) / 2, 24);
        
        // 2R label
        const tick_len = 8;
        const label_line_x = A.x + 30;
        drawLine(label_line_x, A.y, label_line_x, B.y);
        drawLine(label_line_x - tick_len / 2, A.y, label_line_x + tick_len / 2, A.y);
        drawLine(label_line_x - tick_len / 2, B.y, label_line_x + tick_len / 2, B.y);
        drawText("2R", label_line_x + 10, (A.y + B.y) / 2, 24);
        
        // Angle alpha
        const vec_AO = { x: O.x - A.x, y: O.y - A.y };
        const vec_AB = { x: B.x - A.x, y: B.y - A.y };
        const angle_AO = Math.atan2(vec_AO.y, vec_AO.x);
        const angle_AB = Math.atan2(vec_AB.y, vec_AB.x);
        drawAngleArc(A.x, A.y, 30, angle_AO, angle_AB);
        
        const mid_angle = (angle_AO + angle_AB) / 2;
        drawText("α", A.x + 40 * Math.cos(mid_angle), A.y + 40 * Math.sin(mid_angle), 24);

        // Figure label
        drawText("Fig. 1.58", 620, 420, 24);
    }
    
    // Execute drawing functions
    drawFig1_57();
    drawFig1_58();

</script>
</body>
</html>